﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Actions = AEM.Data.BLL.Actions;

namespace AEM.Controls
{
    /// <summary>
    /// LiftModel.xaml 的交互逻辑
    /// </summary>
    public partial class LiftModel : UserControl
    {
        ContextMenu menu;
        string[] floors;
        public LiftModel()
        {
            InitializeComponent();
        }

        private static void OnLiftIDChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                Data.Model.LiftInfo model = Data.DAL.LiftInfo.Select((int)args.NewValue);
                if (null == model) { (sender as LiftModel).lift_name.Text = (sender as LiftModel).TryFindResource("NoID") as string; return; }

                InitModelInfo(sender as LiftModel, model);
            }
        }

        private static void InitModelInfo(LiftModel model, Data.Model.LiftInfo r)
        {
            model.menu = new ContextMenu();
            InitializeMenu(model, r);
            model.lift_name.Text = r.ShortName;
            model.floors = r.LiftActualFloor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            model.floorInfo.Children.Clear();

            
            if (model.floors.Length < model.MaxFloors)
            {
                Canvas cv = new Canvas();
                cv.Width = 40;
                cv.Height = 0;
                for (int i = 0; i < model.MaxFloors - model.floors.Length; i++)
                {
                    cv.Height += model.FloorHeight - 1;
                    model.Height = model.MaxHeight = model.MinHeight += model.FloorHeight - 1;
                }
                model.floorInfo.Children.Add(cv);
            }
            for (int i = model.floors.Length; i > 0; i--)
            {
                FloorModel fl = new FloorModel();
                model.RegisterName("f" + i, fl);
                fl.Height = model.FloorHeight;
                fl.Name = "f" + i;
                fl.Tag = i;
                fl.ContextMenu = model.menu;
                fl.FloorName = model.floors[i - 1];
                fl.MouseDown += new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
                {
                    fl.ContextMenu.Tag = (sender as FloorModel).Tag;
                    fl.ContextMenu.Items[0] = new MenuItem { IsEnabled = false, Header = (string)model.TryFindResource("SelectedFloor") + (sender as FloorModel).FloorName };
                    fl.ContextMenu.IsOpen = true;
                });
                model.floorInfo.Children.Add(fl);
                model.Height = model.MaxHeight = model.MinHeight += fl.Height - 1;// 9;
                fl.ContextMenu.Opened += new RoutedEventHandler((object sender, RoutedEventArgs e) =>
                {
                    try
                    {
                        int power = (int)Data.Enum.ControlPoints.HallCall;
                        (fl.ContextMenu.Items[2] as MenuItem).IsEnabled = Common.PermissionManager.hasPower(power) && !((int)fl.ContextMenu.Tag == model.floors.Length);
                        (fl.ContextMenu.Items[3] as MenuItem).IsEnabled = Common.PermissionManager.hasPower(power) && !((int)fl.ContextMenu.Tag == 1);
                    }
                    catch { }
                });
            }
        }

        private static void InitializeMenu(LiftModel m, Data.Model.LiftInfo r)
        {
            m.menu.Items.Add(new MenuItem { IsEnabled = false, Header = m.TryFindResource("SelectedFloor") as string });

            AddMenuItem(m, (string)m.TryFindResource("RemoteCall"), true, r.LiftNum, r.LiftCOM, 1, (int)Data.Enum.ControlPoints.RemoteCall);
            AddMenuItem(m, (string)m.TryFindResource("HallAscending"), true, r.LiftNum, r.LiftCOM, 5, (int)Data.Enum.ControlPoints.HallCall);
            AddMenuItem(m, (string)m.TryFindResource("HallDescending"), true, r.LiftNum, r.LiftCOM, 6, (int)Data.Enum.ControlPoints.HallCall);
            AddMenuItem(m, (string)m.TryFindResource("VIPCall"), true, r.LiftNum, r.LiftCOM, 7, (int)Data.Enum.ControlPoints.VIPCall);
        }

        private static void AddMenuItem(LiftModel m, string name, bool type, int id, string com, int command, int power)
        {
            MenuItem mi = new MenuItem();
            mi.IsEnabled = Common.PermissionManager.hasPower(power);
            mi.Header = name;
            mi.Click += new RoutedEventHandler((object sender, RoutedEventArgs e) =>
            {
                int f = (int)((sender as MenuItem).Parent as ContextMenu).Tag;
                if (null != Actions.SerialPorts.Regulate)
                    Actions.SerialPorts.Regulate.BeginInvoke(true, id, com,
                        byte.Parse(command.ToString(), NumberStyles.HexNumber), f, new AsyncCallback(Actions.SerialPorts.RegulateCallback), null);
                if (command == 1)
                    m.FloorRing = f.ToString();
                if (command == 7)
                    m.VipRing = f.ToString();

            });
            m.menu.Items.Add(mi);
        }

        private static void OnLiftRisingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                if ((bool)args.NewValue)
                {
                    (sender as LiftModel).up_ring_status.Fill = new SolidColorBrush(Color.FromRgb(0xEF, 0xEF, 0xEF));
                }
                else
                {
                    (sender as LiftModel).up_ring_status.Fill = new SolidColorBrush(Color.FromRgb(0x4D, 0x4D, 0x4D));
                }
            }
        }

        private static void OnLiftDescendingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                if ((bool)args.NewValue)
                {
                    (sender as LiftModel).down_ring_status.Fill = new SolidColorBrush(Color.FromRgb(0xEF, 0xEF, 0xEF));
                }
                else
                {
                    (sender as LiftModel).down_ring_status.Fill = new SolidColorBrush(Color.FromRgb(0x4D, 0x4D, 0x4D));
                }
            }
        }

        private static void OnDoorStatusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                Storyboard s = (Storyboard)(sender as LiftModel).FindResource("DoorCloseStoryboard");
                if ((bool)args.NewValue)
                {
                    s = (Storyboard)(sender as LiftModel).FindResource("DoorOpenStoryboard");
                }
                (sender as LiftModel).BeginStoryboard(s);
            }
        }

        private static void OnFloorNowChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                FloorModel nfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.NewValue);
                FloorModel ofl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.OldValue);
                if (null != ofl) ofl.Style = (Style)Application.Current.TryFindResource("floor_normal");
                if (null != nfl)
                {
                    nfl.Style = (Style)Application.Current.TryFindResource("floor_now");
                    nfl.IsVipRing = Visibility.Hidden;
                    nfl.IsInnerRing = Visibility.Hidden;
                }
            }
        }

        private static void OnFloorRingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                FloorModel rfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.NewValue);
                //if (null != rfl) rfl.Style = (Style)Application.Current.TryFindResource("floor_ring");
            }
            else
            {
                FloorModel rfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.NewValue);
                if (null != rfl) rfl.Style = (Style)Application.Current.TryFindResource("floor_normal");
            }
        }

        private static void OnVipRingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                FloorModel rfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.NewValue);
                if (null != rfl) rfl.IsVipRing = Visibility.Visible;
            }
            else
            {
                FloorModel rfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + (string)args.NewValue);
                if (null != rfl) rfl.IsVipRing = Visibility.Hidden;
            }
        }

        private static void OnInnerRingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                try
                {
                    IEnumerable<FloorModel> ie = (sender as LiftModel).floorInfo.Children.OfType<FloorModel>();
                    Array.ForEach<FloorModel>(ie.ToArray<FloorModel>(), new Action<FloorModel>((v) =>
                    {
                        v.IsInnerRing = Visibility.Hidden;
                    }));
                    foreach (int i in (List<int>)args.NewValue)
                    {
                        FloorModel rfl = (FloorModel)(sender as LiftModel).floorInfo.FindName("f" + i);
                        if (null != rfl) rfl.IsInnerRing = Visibility.Visible;
                    }
                }
                catch { }
            }
        }

        private static void OnLiftStatusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            if (args.NewValue != args.OldValue)
            {
                LiftModel m = (sender as LiftModel);
                string ls = "lift_status_normal";
                Data.Enum.LiftStatus s = (Data.Enum.LiftStatus)args.NewValue;
                switch (s)
                {
                    case Data.Enum.LiftStatus.Fault:
                        ls = "lift_status_fault";
                        break;
                    case Data.Enum.LiftStatus.Driver:
                        ls = "lift_status_driver";
                        break;
                    case Data.Enum.LiftStatus.Fire:
                        ls = "lift_status_fire";
                        break;
                    case Data.Enum.LiftStatus.Locked:
                        ls = "lift_status_locked";
                        break;
                    case Data.Enum.LiftStatus.NC:
                        ls = "lift_status_nc";
                        break;
                    case Data.Enum.LiftStatus.Overhaul:
                        ls = "lift_status_overhaul";
                        break;
                    case Data.Enum.LiftStatus.Normal:
                    default:
                        ls = "lift_status_normal";
                        break;
                }
                (sender as LiftModel).lift_status.Style = (Style)Application.Current.TryFindResource(ls);
                (sender as LiftModel).text_status.Text = (string)Application.Current.TryFindResource(s.ToString());
            }
        }


        #region 以下注册属性
        /// <summary>
        /// 数据库内电梯信息ID
        /// </summary>
        public static readonly DependencyProperty LiftIDProperty =
            DependencyProperty.Register("LiftID", typeof(int), typeof(LiftModel),
            new FrameworkPropertyMetadata(0, new PropertyChangedCallback(OnLiftIDChanged)));

        /// <summary>
        /// 数据库内电梯信息ID
        /// </summary>
        public int LiftID
        {
            get { return (int)GetValue(LiftIDProperty); }
            set { SetValue(LiftIDProperty, value); }
        }

        /// <summary>
        /// 电梯运行方向,上行true有效 false无效
        /// </summary>
        public static readonly DependencyProperty LiftRisingProperty =
            DependencyProperty.Register("LiftRising", typeof(bool), typeof(LiftModel),
            new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnLiftRisingChanged)));

        /// <summary>
        /// 电梯运行方向,上行true有效 false无效
        /// </summary>
        public bool LiftRising
        {
            get { return (bool)GetValue(LiftRisingProperty); }
            set { SetValue(LiftRisingProperty, value); }
        }

        /// <summary>
        /// 电梯运行方向,下行true有效 false无效
        /// </summary>
        public static readonly DependencyProperty LiftDescendingProperty =
            DependencyProperty.Register("LiftDescending", typeof(bool), typeof(LiftModel),
            new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnLiftDescendingChanged)));

        /// <summary>
        /// 电梯运行方向,下行true有效 false无效
        /// </summary>
        public bool LiftDescending
        {
            get { return (bool)GetValue(LiftDescendingProperty); }
            set { SetValue(LiftDescendingProperty, value); }
        }

        /// <summary>
        /// 电梯门状态,true开启,false关闭
        /// </summary>
        public static readonly DependencyProperty DoorStatusProperty =
            DependencyProperty.Register("DoorStatus", typeof(bool), typeof(LiftModel),
            new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnDoorStatusChanged)));

        /// <summary>
        /// 电梯门状态,true开启,false关闭
        /// </summary>
        public bool DoorStatus
        {
            get { return (bool)GetValue(DoorStatusProperty); }
            set { SetValue(DoorStatusProperty, value); }
        }

        /// <summary>
        /// 当前电梯楼层位置
        /// </summary>
        public static readonly DependencyProperty FloorNowProperty =
            DependencyProperty.Register("FloorNow", typeof(string), typeof(LiftModel),
            new FrameworkPropertyMetadata("0", new PropertyChangedCallback(OnFloorNowChanged)));

        /// <summary>
        /// 当前电梯楼层位置
        /// </summary>
        public string FloorNow
        {
            get { return (string)GetValue(FloorNowProperty); }
            set { SetValue(FloorNowProperty, value); }
        }

        /// <summary>
        /// 招唤的楼层
        /// </summary>
        public static readonly DependencyProperty FloorRingProperty =
            DependencyProperty.Register("FloorRing", typeof(string), typeof(LiftModel),
            new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnFloorRingChanged)));

        /// <summary>
        /// 招唤的楼层
        /// </summary>
        public string FloorRing
        {
            get { return (string)GetValue(FloorRingProperty); }
            set { SetValue(FloorRingProperty, value); }
        }

        /// <summary>
        /// VIP招唤的楼层
        /// </summary>
        public static readonly DependencyProperty VipRingProperty =
            DependencyProperty.Register("VipRing", typeof(string), typeof(LiftModel),
            new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnVipRingChanged)));

        /// <summary>
        /// VIP招唤的楼层
        /// </summary>
        public string VipRing
        {
            get { return (string)GetValue(VipRingProperty); }
            set { SetValue(VipRingProperty, value); }
        }

        /// <summary>
        /// 内部招唤的楼层
        /// </summary>
        public static readonly DependencyProperty InnerRingProperty =
            DependencyProperty.Register("InnerRing", typeof(List<int>), typeof(LiftModel),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnInnerRingChanged)));

        /// <summary>
        /// 内部招唤的楼层
        /// </summary>
        public List<int> InnerRing
        {
            get { return (List<int>)GetValue(InnerRingProperty); }
            set { SetValue(InnerRingProperty, value); }
        }

        /// <summary>
        /// 电梯状态
        /// </summary>
        public static readonly DependencyProperty LiftStatusProperty =
            DependencyProperty.Register("LiftStatus", typeof(Data.Enum.LiftStatus), typeof(LiftModel),
            new FrameworkPropertyMetadata(Data.Enum.LiftStatus.NC, new PropertyChangedCallback(OnLiftStatusChanged)));

        /// <summary>
        /// 电梯状态
        /// </summary>
        public Data.Enum.LiftStatus LiftStatus
        {
            get { return (Data.Enum.LiftStatus)GetValue(LiftStatusProperty); }
            set { SetValue(LiftStatusProperty, value); }
        }


        public static readonly DependencyProperty FloorHeightProperty =
            DependencyProperty.Register("FloorHeight", typeof(int), typeof(LiftModel),
            new FrameworkPropertyMetadata(10));

        public int FloorHeight
        {
            get { return (int)GetValue(FloorHeightProperty); }
            set { SetValue(FloorHeightProperty, value); }
        }

        public static readonly DependencyProperty MaxFloorsProperty =
            DependencyProperty.Register("MaxFloors", typeof(int), typeof(LiftModel),
            new FrameworkPropertyMetadata(2));

        public int MaxFloors
        {
            get { return (int)GetValue(MaxFloorsProperty); }
            set { SetValue(MaxFloorsProperty, value); }
        }
        #endregion


    }
}
